package com.proxy.server.backend.nio.adapter;

import com.proxy.common.constant.CapabilitiesType;
import com.proxy.common.packet.AuthPacket;
import com.proxy.common.packet.BinaryPacket;
import com.proxy.common.packet.HandshakePacket;
import com.proxy.common.packet.Reply323Packet;
import com.proxy.common.utils.CharsetUtil;
import com.proxy.common.utils.SecurityUtil;
import com.proxy.server.backend.nio.NioBackendClient;
import com.proxy.server.backend.nio.NioBackendConnection;
import com.proxy.server.context.AppContext;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.nio.charset.Charset;
import java.util.Map;

/**
 * Created by liufish on 16/7/15.
 */
public class BackendCoreAdapter extends ChannelInboundHandlerAdapter{

    /**
     * 后端存储登录后的异步对象。
     */
    private Map<Channel,NioBackendConnection> connections;

    private NioBackendClient client;

    public BackendCoreAdapter(Map<Channel,NioBackendConnection> connections,NioBackendClient client){

        this.connections = connections;
        this.client = client;
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        NioBackendConnection connection = new NioBackendConnection(this.client);
        connection.setStatus(NioBackendConnection.STATUS_CREATE);
        connections.put(ctx.channel(),connection);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        connections.remove(ctx.channel());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

      /*  final BinaryPacket bin =  (BinaryPacket)msg;

        final NioBackendConnection connection = connections.get(ctx.channel());

        if(connection.getStatus() == NioBackendConnection.STATUS_CREATE){
            //未认证
            HandshakePacket handshakePacket = new HandshakePacket();
            handshakePacket.read(bin);

            AuthPacket authPacket = new AuthPacket();
            authPacket.packetId = ++ handshakePacket.packetId;
            authPacket.clientFlags = CapabilitiesType.getServerCapabilities();
            authPacket.maxPacketSize =  1024*1024*16 ; //16M
            authPacket.charsetIndex = handshakePacket.serverCharsetIndex;
            authPacket.user = (client.getNode().getUser());
            final byte[] seed = handshakePacket.seed;
            connection.setSeed(seed);

            int charsetIndex = handshakePacket.serverCharsetIndex;
            byte[] password = client.getNode().getPassword().getBytes(Charset.forName(CharsetUtil.getCharset(charsetIndex)));
            byte[] restOfScramble = handshakePacket.restOfScrambleBuff;
            byte[] authSeed = new byte[seed.length + restOfScramble.length];
            System.arraycopy(seed, 0, authSeed, 0, seed.length);
            System.arraycopy(restOfScramble, 0, authSeed, seed.length, restOfScramble.length);
            authPacket.password = SecurityUtil.scramble411(password, authSeed);
            authPacket.database = client.getNode().getSchema();
            connection.setStatus(NioBackendConnection.STATUS_UN_HANDSHAKE);
            ctx.writeAndFlush(authPacket);
            return;
        }

        //认证过程
        if(connection.getStatus() == NioBackendConnection.STATUS_UN_HANDSHAKE){
            switch (bin.body[0]){
                case  0x00:
                    //success
                    connection.setStatus(NioBackendConnection.STATUS_HANDSHAKE);
                    break;
                case (byte)0xff :
                    //fail
                    connection.setStatus(NioBackendConnection.STATUS_FAIL_HANDSHAKE);
                    ctx.close();
                    break;
                case (byte) 0xfe:
                    // 发送323响应认证数据包
                    Reply323Packet reply323Packet = new Reply323Packet();
                    reply323Packet.read(bin);
                    if (client.getNode().getPassword() != null && client.getNode().getPassword().length() > 0) {
                        byte[] seed323 = SecurityUtil.scramble323(client.getNode().getPassword(), new String(connection.getSeed())).getBytes();
                        reply323Packet.seed = seed323;
                    }
                    reply323Packet.writeBuffer(ctx.channel().alloc().buffer());
                    connection.setStatus(NioBackendConnection.STATUS_HALF_HANDSHAKE);
                    break;
            }

            return;
        }
        //半包认证过程
        if(connection.getStatus() == NioBackendConnection.STATUS_HALF_HANDSHAKE){
            switch (bin.body[0]) {
                case 0x00:
                    //success
                    connection.setStatus(NioBackendConnection.STATUS_HANDSHAKE);
                    break;
                case (byte) 0xff:
                    //fail
                    connection.setStatus(NioBackendConnection.STATUS_FAIL_HALF_HANDSHAKE);
                    ctx.close();
                    break;
            }
            return;
        }

        connection.getReceiver().receive(bin);

*/
    }

    
}
